package cn.edu.wynu;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

// ATM类：代表了ATM系统，负责对账户信息处理以及对外提供业务需求
public class ATM {
    // [] 存储系统全部用户的账户信息
    private ArrayList<Account> accounts = new ArrayList<>();
    private Scanner sc = new Scanner(System.in);
    private Account loginAcc; // 记住登录后的用户账户

    // 1、启动ATM系统，展示欢迎界面
    public void start(){
        while (true) {
            System.out.println("=====欢迎您进入ATM系统=====");
            System.out.println("1、用户登录");
            System.out.println("2、用户开户");
            System.out.println("请选择：");
            int command = sc.nextInt();
            switch (command){
                case 1:
                    // 用户登录
                    login();
                    break;
                case 2:
                    // 用户开户
                    createAccount();
                    break;
                default:
                    System.out.println("输入错误，请重新输入！");
                    break;
            }
        }
    }

    // 2、完成用户开户操作
    private void createAccount(){
        System.out.println("======用户开户======");
        // (1)创建一个账户对象，用于封装用户的开户信息
        Account acc = new Account();

        // (2)需要用户输入自己的开户信息，赋值给账户对象
        System.out.println("请输入用户名:");
        String name = sc.next();
        acc.setUserName(name);

        // 选择性别
        while (true) {
            System.out.println("请输入您的性别：");
            char sex = sc.next().charAt(0); // “男” “女”
            if(sex == '男' || sex == '女'){
                acc.setSex(sex);
                break;
            }else{
                System.out.println("输入性别有误，请重新输入！");
            }
        }

        // 输入密码
        while (true) {
            System.out.println("请输入账户密码：");
            String password = sc.next();
            System.out.println("请输入账户确认密码：");
            String okpassword = sc.next();
            // 判断两次密码是否一致
            if(okpassword.equals(password)){
                acc.setPassword(okpassword);
                break;
            }else {
                System.out.println("两次输入密码不一致，请重新输入！");
            }
        }

        // 输入取现额度
        System.out.println("请输入您的取现额度：");
        double limit = sc.nextDouble();
        acc.setLimit(limit);

        // 重点：需要为这个账户生成一个卡号（由系统自动生成，8位数字，唯一且不可重复）
        // 定义了一个方法:createCardId()，用来返回一个不重复的新卡号。
        // 方法里，使用循环生成了8个随机的数字连起来作为卡号，
        // 接着判断该卡号是否与其他账户的卡号重复。
        // 根据该卡号去账户集合中查询账户对象，如果没有查询到账户对象，该卡号不重复，即可返回
        // 如果查询到了账户对象，则使用循环重复以上(2、3、4)步操作。
        String newCardId = createCardId();
        acc.setCardId(newCardId);

        // (3)把账户对象存入到账户集合中
        accounts.add(acc);
        System.out.println("恭喜您，" + acc.getUserName() + "，开户成功！");
        System.out.println("您的卡号为："+acc.getCardId());
    }

    // 返回一个8位数字卡号，且不能重复
    private String createCardId(){
        while (true) {
            // 定义一个String类型的变量，用于存储8位数字卡号
            String cardId = "";
            // 使用8次循环，把每次生成的随机数拼接在cardId上
            Random r = new Random();
            for (int i = 0; i < 8; i++) {
                int data = r.nextInt(10); // 0-9
                cardId += data;
            }
            // 判断cardId是否重复，重复就重新生成，直到不重复为止
            Account acc = getAccountByCardId(cardId);
            if (acc == null){
                // 如果acc为null，说明卡号没有重复，直接返回cardId
                return cardId;
            }
        }
    }

    // 根据卡号查询账户对象返回 account = [c1, c2, c3 ...]
    private Account getAccountByCardId(String cardId){
        // 遍历全部的账户对象
        for (int i = 0; i < accounts.size(); i++) {
            Account acc = accounts.get(i);
            // 判断卡号是否相等
            if(acc.getCardId().equals(cardId)){
                return acc;
            }
        }
        return null; // 卡号不存在
    }

    // 3、完成用户登录操作
    /*
    设计一个登录方法:login，负责完成用户的登录。
    方法里:如果系统无任何账户对象，直接结束登录操作。
    有账户对象，则让用户输入卡号，根据卡号去账户集合中查询账户对象。
    如果没有找到账户对象，说明登录卡号不存在，提示继续输入卡号。
    如果找到了账户对象，说明卡号存在，继续输入密码。
    如果密码不正确，提示继续输入密码。
    如果密码正确，则登陆成功，并给出相应的提示。
    */
    private void login(){
        System.out.println("======用户登录======");
        // (1)判断系统中是否存在账户对象，存在才登录，如果不存在，则结束登录操作
        if(accounts.size() == 0){
            System.out.println("系统暂无账户，请先开户！");
            return; // 没有账户对象，结束登录操作
        }

        // (2)系统中有账户对象，则让用户输入卡号和密码进行登录
        while (true) {
            System.out.println("请输入您的卡号：");
            String cardId = sc.next();

            // (3)判断卡号是否存在
            Account acc = getAccountByCardId(cardId);
            if (acc == null){
                // 说明卡号不存在
                System.out.println("卡号不存在，请重新输入！");
            }else {
                while (true) {
                    // 说明卡号存在，让用户输入密码
                    System.out.println("请输入您的密码：");
                    String password = sc.next();
                    // (4)判断密码是否正确
                    if (acc.getPassword().equals(password)){
                        loginAcc = acc;
                        // 密码正确，登录成功
                        System.out.println("恭喜您，" + acc.getUserName() + "，登录成功，您的卡号是：" + acc.getCardId());
                        // 重点：展示登录后的操作界面
                        // 展示登录后的操作界面
                        showUserCommand();
                        return; // 跳出并结束当前登录方法

                    }else {
                        // 密码不正确，提示用户，重新输入
                        System.out.println("密码不正确，请重新输入！");
                    }
                }
            }
        }
    }

    // 4、展示登录后的操作界面
    private void showUserCommand(){
        while (true) {
            System.out.println("=====" + loginAcc.getUserName() + "，您可以选择如下功能进行账户的查询处理=====");
            System.out.println("1、查询账户");
            System.out.println("2、存款");
            System.out.println("3、取款");
            System.out.println("4、转账");
            System.out.println("5、修改密码");
            System.out.println("6、退出登录");
            System.out.println("7、注销账户");
            System.out.println("请选择：");
            int command = sc.nextInt();
            switch (command){
                case 1:
                    // 查询账户
                    showLoginAccount();
                    break;
                case 2:
                    //存款
                    depositMoney();
                    break;
                case 3:
                    //取款
                    drawMoney();
                    break;
                case 4:
                    //转账
                    transferMoney();
                    break;
                case 5:
                    //修改密码
                    updatePassword();
                    return; // 跳出并结束当前方法
                case 6:
                    //退出登录
                    System.out.println(loginAcc.getUserName() + "，您退出系统成功，欢迎下次光临!");
                    return; // 跳出并结束当前方法
                case 7:
                    //注销账户
                    if(deleteAccount()){
                        // 销户成功，回到欢迎界面
                        return;
                    }
                    break;
                default:
                    System.out.println("输入有误，请重新输入！");
            }
        }
    }

    // 展示当前登录的账户信息
    private void showLoginAccount(){
        System.out.println("======当前登录的账户信息如下======");
        System.out.println("卡号：" + loginAcc.getCardId());
        System.out.println("户主：" + loginAcc.getUserName());
        System.out.println("性别：" + loginAcc.getSex());
        System.out.println("余额：" + loginAcc.getMoney());
        System.out.println("每次取钱限额：" + loginAcc.getLimit());
    }

    // 5、存款
    private void depositMoney() {
        System.out.println("======存款操作======");
        System.out.println("请输入存款金额：");
        double money = sc.nextDouble();

        // 更新当前登录账户的余额
        loginAcc.setMoney(loginAcc.getMoney() + money);
        System.out.println("存入" + money + "，当前余额为："+ loginAcc.getMoney());
    }

    // 6、取款
    private void drawMoney() {
        System.out.println("======取款操作======");
        // (1)判断当前登录账户余额是否足够，如果不足100元，则提示取款失败，结束当前方法
        if (loginAcc.getMoney() < 100){
            System.out.println("余额不足，取款失败！");
            return;
        }

        // (2)让用户输入取款金额
        while (true) {
            System.out.println("请输入取款金额：");
            double money = sc.nextDouble();

            // (3)判断账户余额是否足够
            if(loginAcc.getMoney() >= money) {
                // 账户中的余额是足够的
                // (4)判断当前取款金额是否超过限额
                if (money > loginAcc.getLimit()){
                    System.out.println("您当前取款金额超过了限额，每次最多可取：" + loginAcc.getLimit());
                }else {
                    // 代表可以开始取钱了，更新当前账户余额
                    loginAcc.setMoney(loginAcc.getMoney() - money);
                    System.out.println("成功取款" + money + "，当前余额为：" + loginAcc.getMoney());
                    break; // 结束当前方法
                }
            }else{
                System.out.println("余额不足，取款失败，您账户中的余额为：" + loginAcc.getMoney());
            }
        }
    }

    // 7、转账
    private void transferMoney() {
        System.out.println("======转账操作======");
        // (1)判断系统中是否有其他账户，至少有两个账户才能转账
        if(accounts.size() < 2){
            System.out.println("系统暂无除自己以外的其他账户，无法转账！");
            return; // 没有账户对象，结束登录操作
        }

        // (2)判断自己的账户中是否有钱
        if(loginAcc.getMoney() == 0){
            System.out.println("您的账户余额为0，无法转账！");
            return;
        }

        while (true) {
            // (3)真正开始转账操作
            System.out.println("请输入对方的卡号：");
            String cardId = sc.next();

            // (4)判断这个卡号是否正确
            Account acc = getAccountByCardId(cardId);
            if(acc == null){
                System.out.println("卡号不存在，转账失败！");
            }else {
                // 对方账户存在，继续认证对方用户姓氏
                String name = "*" + acc.getUserName().substring(1); // 小邓

                System.out.println("请输入【" + name + "】的姓氏");
                String preName = sc.next();
                // (5)判断这个姓氏是否正确
                if(acc.getUserName().startsWith(preName)) {
                    while (true) {
                        // 代表用户姓氏正确，开始转账操作
                        System.out.println("请输入转账金额：");
                        double money = sc.nextDouble();
                        // (6)判断转账金额是否没有超过自己的余额
                        if(loginAcc.getMoney() >= money){
                            // 转账金额没有超过自己的余额，开始转账操作
                            // 更新自己账户余额
                            loginAcc.setMoney(loginAcc.getMoney() - money);
                            // 更新对方账户余额
                            acc.setMoney(acc.getMoney() + money);
                            System.out.println("成功转账" + money + "元到【" + acc.getUserName() + "】的账户！");
                            return; // 结束当前转账方法
                        }else {
                            System.out.println("转账失败，您的余额不足，当前余额为：" + loginAcc.getMoney());
                        }
                    }
                }else {
                    System.out.println("您认证的姓氏不正确，转账失败！");
                }
            }
        }
    }

    // 8、销户操作
    private boolean deleteAccount() {
        System.out.println("======销户操作======");
        // (1)判断是否确认销户
        System.out.println("您确认要销户吗？(Y/N y/n)");
        String command = sc.next();
        switch (command){
            case "Y":
            case "y":
                // 确定销户
                // (2)判断当前账户余额是否为0
                if(loginAcc.getMoney() == 0){
                    // 代表可以销户了
                    accounts.remove(loginAcc); // 从集合中移除当前登录的账户对象
                    System.out.println("销户成功！");
                    return true; // 返回true，代表销户成功
                }else {
                    System.out.println("您的账户余额不为0，不能销户！");
                    return false; // 返回false，代表不销户
                }
            default:
                System.out.println("销户操作已取消！");
                return false; // 返回false，代表不销户
        }

    }

    // 9、修改密码
    private void updatePassword() {
        System.out.println("======修改密码======");
        while (true) {
            // (1)提醒用户认证当前账户密码
            System.out.println("请您输入当前账户密码：");
            String password = sc.next();

            // (2)判断用户输入的密码是否正确
            if(loginAcc.getPassword().equals(password)){
                while (true) {
                    // (3)密码正确，开始修改密码操作
                    System.out.println("请输入新密码：");
                    String newPassword = sc.next();

                    System.out.println("请再次输入确认密码：");
                    String okPassword = sc.next();

                    // (4)判断两次密码是否一致
                    if(okPassword.equals(newPassword)){
                        // 代表两次密码一致，可以修改
                        loginAcc.setPassword(okPassword); // 更新当前登录账户的密码
                        System.out.println("密码修改成功！");
                        return; // 结束当前方法
                    }else {
                        System.out.println("输入的两次密码不一致，请重新输入！");
                    }
                }
            }else {
                System.out.println("您输入的密码不正确");
            }
        }

    }














}
